package control;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;

import pdf.PDFfile;

import server.EchoServer;
import server.mysqlConnection;

/**
 * @author MENASHE
 * *   This class responsible for the operation Inventory ManageMent , when the client wants to activate this operation he inserts data in the GUI client
,the data we insert into array string that will send to the server, In the server we maps the message by checking the first string (see AbstractControl).*/
 
public class InventoryControl extends AbstractControl {

	String bid,copy;
	public Object anlyze(String[] msg) 
	{
		String[][] x=null;
		ArrayList<Object> result =new ArrayList<Object>();
		bid=msg[3];
		copy=msg[2];
		switch(msg[1])
		{		
			case "truetruetruetrue":
				x=mysqlConnection.select("Select bid,name,author,location,amount,edition,printDate,purchaseDate, category, description,ispopular,pathindex from booktitle WHERE name like " + msg[2] + " AND author like " + msg[3] + " AND category like " +msg[4] + " AND description like " +msg[5],12);
				result.add("InventoryS");
				result.add(x);
				break;
			case "truefalsefalsefalse":
				x=mysqlConnection.select("Select bid,name,author,location,amount,edition,printDate,purchaseDate, category, description,ispopular,pathindex from booktitle WHERE name like " + msg[2],12);
				result.add("InventoryS");
				result.add(x);
				break;
			case "falsetruefalsefalse":
				x=mysqlConnection.select("Select bid,name,author,location,amount,edition,printDate,purchaseDate, category, description,ispopular,pathindex from booktitle WHERE author like " + msg[3],12);
				result.add("InventoryS");
				result.add(x);
				break;
			case "falsefalsetruefalse":
				x=mysqlConnection.select("Select bid,name,author,location,amount,edition,printDate,purchaseDate, category, description,ispopular,pathindex from booktitle WHERE category like " + msg[4],12);
				result.add("InventoryS");
				result.add(x);
				break;
			case "falsefalsefalsetrue":
				x=mysqlConnection.select("Select bid,name,author,location,amount,edition,printDate,purchaseDate, category, description,ispopular,pathindex from booktitle WHERE description like " + msg[5],12);
				result.add("InventoryS");
				result.add(x);
				break;
			case "truetruefalsefalse":
				x=mysqlConnection.select("Select bid,name,author,location,amount,edition,printDate,purchaseDate, category, description,ispopular,pathindex from booktitle WHERE name like " + msg[2] + " AND author like " + msg[3],12);
				result.add("InventoryS");
				result.add(x);
				break;
			case "truefalsetruefalse":
				x=mysqlConnection.select("Select bid,name,author,location,amount,edition,printDate,purchaseDate, category, description,ispopular,pathindex from booktitle WHERE name like " + msg[2] + " AND category like " + msg[4],12);
				result.add("InventoryS");
				result.add(x);
				break;
			case "truefalsefalsetrue":
				x=mysqlConnection.select("Select bid,name,author,location,amount,edition,printDate,purchaseDate, category, description,ispopular,pathindex from booktitle WHERE name like " + msg[2] + " AND description like " + msg[5],12);
				result.add("InventoryS");
				result.add(x);
				break;
			case "falsetruefalsetrue":
				x=mysqlConnection.select("Select bid,name,author,location,amount,edition,printDate,purchaseDate, category, description,ispopular,pathindex from booktitle WHERE author like " + msg[3] + " AND description like " + msg[5],12);
				result.add("InventoryS");
				result.add(x);
				break;
			case "falsetruetruefalse":
				x=mysqlConnection.select("Select bid,name,author,location,amount,edition,printDate,purchaseDate, category, description,ispopular,pathindex from booktitle WHERE author like " + msg[3] + " AND category like " + msg[4],12);
				result.add("InventoryS");
				result.add(x);
				break;
			case "falsefalsetruetrue":
				x=mysqlConnection.select("Select bid,name,author,location,amount,edition,printDate,purchaseDate, category, description,ispopular,pathindex from booktitle WHERE description like " + msg[5] + " AND category like " + msg[4],12);
				result.add("InventoryS");
				result.add(x);
				break;
			case "falsetruetruetrue":
				x=mysqlConnection.select("Select bid,name,author,location,amount,edition,printDate,purchaseDate, category, description,ispopular,pathindex from booktitle WHERE description like " + msg[5] + " AND category like " + msg[4] + " AND author like " + msg[3],12);
				result.add("InventoryS");
				result.add(x);
				break;
			case "truefalsetruetrue":
				x=mysqlConnection.select("Select bid,name,author,location,amount,edition,printDate,purchaseDate, category, description,ispopular,pathindex from booktitle WHERE description like " + msg[5] + " AND name like " + msg[2] + " AND author like " + msg[3],12);
				result.add("InventoryS");
				result.add(x);
				break;
			case "truetruefalsetrue":
				x=mysqlConnection.select("Select bid,name,author,location,amount,edition,printDate,purchaseDate, category, description,ispopular,pathindex from booktitle WHERE description like " + msg[5] + " AND name like " + msg[2] + " AND category like " + msg[4],12);
				result.add("InventoryS");
				result.add(x);
				break;
			case "truetruetruefalse":
				x=mysqlConnection.select("Select bid,name,author,location,amount,edition,printDate,purchaseDate, category, description,ispopular,pathindex from booktitle WHERE category like " + msg[3] + " AND name like " + msg[2] + " AND category like " + msg[4],12);
				result.add("InventoryS");
				result.add(x);
				break;
			case "Remove":
				removeCopy(result);				
				break;	
			case "AddCopy":
				addCopy(result,msg);
				break;
			case "New Title":
				try 
				{
					newTitle(result,msg);
				} catch (IOException e) 
				{
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				break;
			
		}
		return result;

	}
	
	/** adds a new copy to the requested books, modifies the "books" table in the DB.
	 * @param s , the result array to be returned in the end of "analyze".
	 * @param msg , the message received from client, containing the necessary data to make changes in the DB  
	 */
	public void addCopy(ArrayList<Object> s,String[] msg)
	{
		int copy=(getMaxCopy(msg[2])+1);
		bid=msg[2];
		s.add("AddCopy");

		Queue<Integer> q1=EchoServer.bookOrdersQueue.get(Integer.parseInt(bid));
		int size=((ArrayBlockingQueue<Integer>)q1).remainingCapacity()+q1.size();
		Queue<Integer> q=new ArrayBlockingQueue<Integer>(size+1);	
		while(q1.size()>0)
		{
			q.add(q1.poll());
		}
		if(q.size()>0)
		{	
			DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
			Calendar cal = Calendar.getInstance();
			String today = new String("'");
			today += dateFormat.format(cal.getTime());
			today += "'";			
			EchoServer.sendEmailNotification(getEmail(q.element().toString()),"The book you ordered is now waiting for you in the library.");	
			Integer sid=q.poll();
			mysqlConnection.update("INSERT into saveorderlist SET sid="+sid+", bid="+bid+", copy="+copy+", date="+today+";"); 
			mysqlConnection.update("DELETE FROM orders WHERE sid="+sid+" AND bid="+bid+";");		
			mysqlConnection.update("UPDATE orders SET indexinqueue=indexinqueue-1 WHERE bid="+bid+";");
			String query=new String("INSERT INTO test.books SET bid="+msg[2]+", copy="+(getMaxCopy(msg[2])+1)+", name=\""+msg[3]+"\", author=\""+msg[4]+"\", category=\""+msg[5]+"\", description=\""+msg[6]+"\", location=\""+msg[7]+"\", ispopular="+msg[11]+", isborrowed=0, pathindex=\""+msg[12]+"\", expectedReturnDate=null, edition="+msg[8]+", printDate=\""+msg[9]+"\", purchaseDate=\""+msg[10]+"\";");
			s.add(mysqlConnection.update(query));	
		}
		else
		{
			String query=new String("INSERT INTO test.books SET bid="+msg[2]+", copy="+(getMaxCopy(msg[2])+1)+", name=\""+msg[3]+"\", author=\""+msg[4]+"\", category=\""+msg[5]+"\", description=\""+msg[6]+"\", location=\""+msg[7]+"\", ispopular="+msg[11]+", isborrowed=0, pathindex=\""+msg[12]+"\", expectedReturnDate=null, edition="+msg[8]+", printDate=\""+msg[9]+"\", purchaseDate=\""+msg[10]+"\";");
			s.add(mysqlConnection.update(query));	
		}
		

		EchoServer.bookOrdersQueue.remove(Integer.parseInt(bid));
		EchoServer.bookOrdersQueue.put(Integer.parseInt(bid), q);
	}
	

	/** remove requested copy from inventory. deletes proper row from "books" table in DB.
	 * @param s , the result array to be returned in the end of "analyze".
	 */
	public void removeCopy(ArrayList<Object> s)
	{
		s.add("Remove");
		if(!checkExist())
		{
			s.add("ERROR: Book does not exist");
			return;
		}
		else if(ReturnControl.isBorrwed(bid, copy))
		{
			s.add("ERROR:  Book is borrowed");
			return;
		}
		int amount=getAmount(bid);
		String query2="SELECT sid FROM test.saveorderlist WHERE bid="+bid+" AND copy="+copy+";";		
		String[][] sid=mysqlConnection.select(query2, 1);
		
		
		String query=new String("DELETE FROM test.books WHERE bid="+bid+" AND copy="+copy+";");
		s.add(mysqlConnection.update(query));	
	

		boolean x;
		if(sid.length!=0)
		{

			x=true;
		}
		else x=false;
		if(amount==1)//if we deleted the last book, we remove the queue from global hashmap
		{
			EchoServer.bookOrdersQueue.remove(Integer.parseInt(bid));		
		}
		else 
		{
			Integer y = EchoServer.bookOrdersQueue.get(Integer.parseInt(bid)).size();


			Queue<Integer> q1=EchoServer.bookOrdersQueue.get(Integer.parseInt(bid));
			
			int size=((ArrayBlockingQueue<Integer>)q1).remainingCapacity()+q1.size();
			Queue<Integer> q=new ArrayBlockingQueue<Integer>(size-1);
	
			
			if(x)
			{
				if(getOrderListCont(bid)+y>=amount-1)
				{
					query="DELETE FROM test.orders WHERE indexinqueue="+y+";";
					mysqlConnection.update(query);	
				}
				String query3=new String("DELETE FROM test.saveorderlist WHERE bid="+bid+" AND copy="+copy+" AND sid="+ sid[0][0] +";");
				s.add(mysqlConnection.update(query3));
				query="UPDATE orders SET indexinqueue=indexinqueue+1 WHERE bid="+bid+";";					
				mysqlConnection.update(query);	
				query="insert into orders set bid=" + bid + ",sid=" + sid[0][0]
						+ ",indexinqueue=1;";
				mysqlConnection.update(query);	
				q.add(Integer.parseInt(sid[0][0]));
				
			}
			
			while((((ArrayBlockingQueue<Integer>) q).remainingCapacity()>0)  &&  q1.size()>0)
			{
				q.add(q1.poll());
			}
			
			EchoServer.bookOrdersQueue.remove(Integer.parseInt(bid));
			EchoServer.bookOrdersQueue.put(Integer.parseInt(bid), q);
		}
		
	}
	
	/** get the maximal copy number with the specified bid
	 * @param bid
	 * @return  maximal copy number with the specified bid
	 */
	public int getMaxCopy(String bid)
	{
		String[][] x=null;
		x=mysqlConnection.select("Select max(copy) from test.books WHERE bid="+bid+" GROUP BY bid;",1);
		return Integer.parseInt(x[0][0]);	
	}
	
	/** get the amount of books with the specified bid
	 * @param bid
	 * @return amount of books with the specified bid
	 */
	public int getAmount(String bid)
	{
		String[][] x=null;
		x=mysqlConnection.select("Select count(copy) from test.books WHERE bid="+bid+" GROUP BY bid;",1);
		return Integer.parseInt(x[0][0]);	
	}
	
	
	
	@Override
	public Boolean checkExist() {
		String rst=mysqlConnection.check("select * from books WHERE bid="+bid+" AND copy="+copy);
		if(rst.compareTo("NotEXIST")==0 || rst.compareTo("FAIL")==0) 
			return false;
		return true;
		
	}
	
	/** adds a new title to inventory, adds a proper row to the books table in the DB
	 * @param s , the result array to be returned in the end of "analyze".
	 * @param msg , the message received from client, containing the necessary data to make changes in the DB 
	 * @throws IOException
	 */
	public void newTitle(ArrayList<Object> s, String[] msg) throws IOException
	{
		s.add("newTitle");
		bid=msg[11];
		if(bidExist())
		{
			s.add("ERROR: Book ID already taken ");
			return;
		}
		
		DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
		Calendar cal = Calendar.getInstance();
		String today = new String("'");
		today += dateFormat.format(cal.getTime());
		today += "'";
		
		File temp = new File(msg[10]);
		PDFfile toSave=new PDFfile(temp);
		
		File temp2 = new File("index/"+temp.getName());

		
		Files.write(temp2.toPath(), toSave.input,StandardOpenOption.CREATE);

		
		for(int i=0;i<Integer.parseInt(msg[8]);i++)
		{
			String query=new String("INSERT INTO test.books SET bid="+msg[11]+", copy="+i+", name=\""+msg[2]+"\", author=\""+msg[3]+"\", category=\""+msg[4]+"\", description=\""+msg[5]+"\", location=\""+msg[6]+"\", ispopular="+msg[12]+", isborrowed=0, edition="+msg[6]+", printDate=\""+msg[7]+"\", purchaseDate="+today+", expectedReturnDate=null, pathindex=\"index/"+temp2.getName()+"\";");
			s.add(mysqlConnection.update(query));		
		}
		 Queue<Integer> q=new ArrayBlockingQueue<Integer>(Integer.parseInt(msg[8]));
		EchoServer.bookOrdersQueue.put(Integer.parseInt(bid), q );
	}
	
	/** uses calls variable "bid" to check if this bid exist in the books table in DB
	 * @return true if it exist, or false if it isn't
	 */
	public Boolean bidExist() {
		String rst=mysqlConnection.check("select * from books WHERE bid="+bid+";");
		if(rst.length()==0 || rst.compareTo("FAIL")==0|| rst.compareTo("NotEXIST")==0) 
			return false;
		return true;
		
	}
	
	
	/** get the number of times this bid appears in the saveorderlist. 
	 * @param bid
	 * @return how many times this bid appears in the saveorderlist. 
	 */
	public int getOrderListCont(String bid)
	{
		String[][] x=null;
		x=mysqlConnection.select("Select count(copy) from test.saveorderlist WHERE bid="+bid+" GROUP BY bid;",1);
		return Integer.parseInt(x[0][0]);	
	}

	
	

}
